package dev.ece.suit.loader.models.dae;

import java.util.Map;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import dev.ece.suit.loader.Material;
import dev.ece.util.lib.Vector3f;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="library_effects")
public class DAEEffects {

	@XmlElement(name="effect")
	private DAEEffect[] effect;
	
	public Material[] toMeterials(Map<String, String> images, Map<String, Integer> materialIndexMap) {
		Material[] materials = null;
		if(effect != null) {
			materials = new Material[effect.length];
			for(int i=0; i<effect.length; i++) {
				materials[i] = effect[i].toMaterial(images);
				materialIndexMap.put(StringUtils.join("#", effect[i].getId()), i);
			}
		}
		return materials;
	}
	
	public DAEEffect[] getEffect() {
		return effect;
	}

	public void setEffect(DAEEffect[] effect) {
		this.effect = effect;
	}

	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="effect")
	public static class DAEEffect {
		
		@XmlAttribute(name="id")
		private String id;
		
		@XmlAttribute(name="name")
		private String name;
		
		@XmlElement(name="profile_COMMON")
		private ProfileCommon profileCommon;
		
		public Material toMaterial(Map<String, String> images) {
			Phong phong = profileCommon.getTechnique().getPhong();
			Texture texture = phong.getDiffuse() != null ? phong.getDiffuse().texture : null;
			String textureName = texture != null ? images.get(StringUtils.join("#", texture.getTexture())) : null;
			Material material = new Material(textureName);
			if(phong.getDiffuse() != null) {
				phong.getDiffuse().fillValue(material.getDiffuse());
			}
			if(phong.getSpecular() != null) {
				phong.getSpecular().fillValue(material.getSpecular());
			}
			if(phong.getShininess() != null) {
				material.setShininess(phong.getShininess().getValue());
			}
			return material;
		}
		
		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public ProfileCommon getProfileCommon() {
			return profileCommon;
		}

		public void setProfileCommon(ProfileCommon profileCommon) {
			this.profileCommon = profileCommon;
		}

	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="profile_COMMON")
	public static class ProfileCommon {
		
		@XmlElement(name="technique")
		private Technique technique;

		public Technique getTechnique() {
			return technique;
		}

		public void setTechnique(Technique technique) {
			this.technique = technique;
		}
		
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="technique")
	public static class Technique {
		
		@XmlAttribute(name="sid")
		private String sid;
		
		@XmlElement(name="phong")
		private Phong phong;

		public String getSid() {
			return sid;
		}

		public void setSid(String sid) {
			this.sid = sid;
		}

		public Phong getPhong() {
			return phong;
		}

		public void setPhong(Phong phong) {
			this.phong = phong;
		}
		
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="phong")
	public static class Phong {
		
		@XmlElement
		private PhongElement emission;
		@XmlElement
		private PhongElement ambient;
		@XmlElement
		private PhongElement diffuse;
		@XmlElement
		private PhongElement specular;
		@XmlElement
		private PhongElement shininess;
		
		public PhongElement getEmission() {
			return emission;
		}
		public void setEmission(PhongElement emission) {
			this.emission = emission;
		}
		public PhongElement getAmbient() {
			return ambient;
		}
		public void setAmbient(PhongElement ambient) {
			this.ambient = ambient;
		}
		public PhongElement getDiffuse() {
			return diffuse;
		}
		public void setDiffuse(PhongElement diffuse) {
			this.diffuse = diffuse;
		}
		public PhongElement getSpecular() {
			return specular;
		}
		public void setSpecular(PhongElement specular) {
			this.specular = specular;
		}
		public PhongElement getShininess() {
			return shininess;
		}
		public void setShininess(PhongElement shininess) {
			this.shininess = shininess;
		}
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="phongElement")
	public static class PhongElement {
		
		@XmlElement
		private String color;
		
		@XmlElement(name="float")
		private Float value;
		
		@XmlElement(name="texture")
		private Texture texture;
		
		public void fillValue(Vector3f value) {
			if(StringUtils.isBlank(color)) {
				value.set(1, 1, 1);
			} else {
				String[] color = StringUtils.split(StringUtils.trimToEmpty(this.color), " ");
				if(color != null && color.length > 2) {
					value.set(
							NumberUtils.toFloat(color[0]), 
							NumberUtils.toFloat(color[1]), 
							NumberUtils.toFloat(color[2]));
				}
			}
		}
		
		public String getColor() {
			return color;
		}
		public void setColor(String color) {
			this.color = color;
		}
		public Float getValue() {
			return value;
		}
		public void setValue(Float value) {
			this.value = value;
		}
		public Texture getTexture() {
			return texture;
		}
		public void setTexture(Texture texture) {
			this.texture = texture;
		}
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="texture")
	public static class Texture {
		
		@XmlAttribute
		private String texture;

		public String getTexture() {
			return texture;
		}

		public void setTexture(String texture) {
			this.texture = texture;
		}
	}
	
}
